# Notes:
# If the script starts behaving strange consider the following options:
# 1) Restart ISE
# 2) IISReset
# 3) Recreate database

$EMIVersion = $Null

function Test-EMIClientInstall()
{
    if ($(Test-Path "C:\Inetpub\wwwroot\Incuity\Bin\DataWorks.MI.Core.dll") -eq $false)
    {
        Throw "DataWorks.MI.Core.dll not found. Is EMI Client intalled on this machine?"
    }
    return $True
}


function Load-EMIClientAssemblies()
{
    $CoreAssembly = [System.Reflection.Assembly]::LoadWithPartialName("DataWorks.MI.Core")
    $CoreClientAssembly = [System.Reflection.Assembly]::LoadWithPartialName("DataWorks.MI.Core.Client")
}


# How to get the version of the Incuity System
function Get-EMIVersion()
{
    if( $Script:EMIVersion -eq $Null)
    {
        $Version = [DataWorks.MI.Core.Client.Globals]::Version
        $Script:EMIVersion = $Version
    }
    return $Version    
}

function Initialize-EMIClient()
{
    [DataWorks.MI.Core.Client.Globals]::Initialize()

}


function Get-InSqlwwAdminToken()
{
    $InSqlwwAdminToken = [DataWorks.MI.Core.Item]::GetInstance("System.Security.Mappings.wwAdminToken")
    if ($InSqlwwAdminToken -eq $Null)
    {
        $InSqlwwAdminToken = New-FixedCredentials -UserName "wwAdmin" -Password "wwAdmin" -TokenName "wwAdminToken"
    }
    return $InSqlwwAdminToken
}


function New-FixedCredentials([string] $UserName, [string] $Password, [string] $TokenName)
{         
    Trap { [DataWorks.MI.Core.Persistence]::AbortTransaction(); [DataWorks.MI.Core.Persistence]::CloseTransaction(); throw }
    &{
        
        $SecurityPath = "Core."

        If ( $Script:EMIVersion.Major -eq 3)
        {
            $SecurityPath = "Core.Security."
        }


        [DataWorks.MI.Core.Persistence]::BeginNewTransaction()
        
        #Get the Mappings collection property of the System.Security system item
        $SecurityItem = [DataWorks.MI.Core.Item]::GetInstance([DataWorks.MI.Core.Namespace.NamespaceProvider]::FQNSecurity)
        [DataWorks.MI.Core.IProperty] $ParentToAddTo = $SecurityItem.Properties["Mappings"]
        
        $ValueBag = New-Object -TypeName "DataWorks.MI.Core.Collections.NamedValueBag"
	
        $ValueBag.Add("SecurityMappingStrategyHolder", $SecurityItem)
        
        #Create new Security Strategy and add it to the System.Security.Mappings property
        $CredentialsStrategy = [DataWorks.MI.Core.Item]::CreateInstance([string] $($SecurityPath + "UseFixedCredentials"), $TokenName , [DataWorks.MI.Core.Collections.NamedValueBag] $ValueBag, [DataWorks.MI.Core.IProperty] $ParentToAddTo)
        
        $ValueBag.Clear()
    
        $ValueBag.Add("UserName", $UserName)
        $ValueBag.Add("Password", [DataWorks.MI.Core.Security.DataEncryptor]::Encrypt($Password))

        $MappedCredentialsProperty = $CredentialsStrategy.Properties["MappedCredentials"]
        
        #Create new SimpleCredential Login and add it to the new Security Strategy's MappedCredential collection property
        #Bug if create instance result is not assigned to variable
        $SimpleCredentials = [DataWorks.MI.Core.Item]::CreateInstance([string] $($SecurityPath + "SimpleCredentials"), "Credentials", $ValueBag, $MappedCredentialsProperty)

    
        [DataWorks.MI.Core.Persistence]::CommitTransaction()
        [DataWorks.MI.Core.Persistence]::CloseTransaction()
        
        
    
        return $CredentialsStrategy
    }
}


function New-InSQLConnector([string] $InSqlConnectorName,[string] $InSqlServerName, $SecurityToken = $(Get-InSqlwwAdminToken), [string] $TimeZone = "Pacific Standard Time" )
{
    $InSQLConnectorTypeItem =  [DataWorks.MI.Core.Item]::GetInstance("System.Sources.InSQL")
    $InSQLConnector = $InSQLConnectorTypeItem.Invoke("CreateInstance", $InSqlConnectorName, $InSqlServerName, $SecurityToken , $TimeZone)
    return $InSQLConnector
}


function Get-EMIFolder([string] $FolderName = "MyInSqlNamespace", [string] $ParentFolder = "NotUsed")
{
    # Get MyEnterprise logical Model folder it is of type Core.LogicalModelRoot
    $LogicalModelFQN = [DataWorks.MI.Core.Namespace.NamespaceProvider]::FQNLogicalModel
    
    # Append new Foldername to create new FQN (Fully qualified name)
    $TargetFolderFQN = [DataWorks.MI.Core.Namespace.FQN]::AppendNamePart($LogicalModelFQN , $FolderName)
    
    # Query the new FQN and see whether this folder already exists
	[DataWorks.MI.Core.Namespace.IItemNsElementInfo] $ElementInfo = [DataWorks.MI.Core.Namespace.NamespaceProvider]::Instance.ResolveFQN($TargetFolderFQN)
    
    # If folder item doesn't exist create new one
    if ( $ElementInfo -eq $null)
    {
        $NewFolderItem = New-EMIFolder -FolderName $FolderName
        return $NewFolderItem
    }
    else
    {
        if ( $ElementInfo.ItemType.IsA("Core.Folder"))
        {
            $TargetFolderItem = $ElementInfo.Item
            return $TargetFolderItem
        }
        else
        {
            throw "Specified FQN exists already, but is not a folder!"
        }
    }
}

function New-EMIFolder([string] $FolderName = "MyInSqlNamespace", [string] $ParentFolder = "NotUsed")
{
    # Another way to get the MyEnterprise root folder item of the logical model
    $RootFolderItem = [DataWorks.MI.Core.Namespace.NamespaceProvider]::Instance[[DataWorks.MI.Core.WellKnownItem]::LogicalModel]
    $ValueBag = New-Object -TypeName "DataWorks.MI.Core.Collections.NamedValueBag"
    [DataWorks.MI.Core.IProperty] $ChildrenProperty = $RootFolderItem.Properties["Children"]
    [DataWorks.MI.Core.IItem] $NewFolderItem = [DataWorks.MI.Core.Item]::CreateInstance("Core.Folder", $FolderName, $ValueBag, $ChildrenProperty)
        
    return $NewFolderItem
}


function Import-AllInSQLTags([string] $EMIFolderPath, [DataWorks.MI.Core.IItem] $InSqlConnector)
{
    $ValueBag = New-Object -TypeName "DataWorks.MI.Core.Collections.NamedValueBag"
    $ValueBag.Add("SourceFolder", [String]::Empty)
    $ValueBag.Add("ImportPublic", $True)
    $ValueBag.Add("ExcludeSystem", $False)
    $ValueBag.Add("ImportPrivate", $True)
    $ValueBag.Add("TargetFolder", [string] $EMIFolderPath)
    $InSqlConnector.InvokeWithNamedParams("ImportItems", $ValueBag)
}

function Wait-ForSyncImportOperationToComplete([int] $PollInterval, [DataWorks.MI.Core.IItem] $InSqlConnector)
{
    While ($True)
    {
        [System.Threading.Thread]::Sleep($PollInterval)
        [string] $LastProgress = $InSqlConnector.Invoke("GetLastSynImportProgress")
        Write-Output "Operation in Progress..."
         If ($LastProgress.StartsWith("Error: "))
         {
            Write-Output $LastProgress
            return $False
         }
         elseif ($LastProgress.EndsWith("Done."))
         {
            Write-Output "Import completed successfully."
            return $True
         }
    }
}

function Remove-EMIItem([string] $ItemFQN)
{
    $ItemToRemove = [DataWorks.MI.Core.Item]::GetInstance($ItemFQN)
    If ($ItemToRemove -ne $Null)
    {
        $ItemToRemove.Delete()
    }
}

function Remove-EMIConnector([string] $ItemFQN)
{
    $ConnectorToRemove = [DataWorks.MI.Core.Item]::GetInstance($ItemFQN)
    If ($ConnectorToRemove -ne $Null)
    {
        $ConnectorToRemove.Invoke("Delete")
    }
}

function Restore-EMIModel()
{
    Remove-EMIItem -ItemFQN "MyEnterprise.NSwwHistorian1"
    Remove-EMIItem -ItemFQN "System.Security.Mappings.wwAdminToken"
    Remove-EMIConnector -ItemFQN "System.Sources.InSQL.wwHistorian1"
}

Test-EMIClientInstall
Load-EMIClientAssemblies
Get-EMIVersion
Initialize-EMIClient
$NewConnectorItem = New-InSQLConnector -InSqlConnectorName "wwHistorian1" -InSqlServerName "InSql80"
$FolderItem = Get-EMIFolder -FolderName "NSwwHistorian1"
$FolderPath = $FolderItem["FullyQualifiedName"]
$FolderPath
Import-AllInSQLTags -EMIFolderPath $FolderPath -InSQLConnector $NewConnectorItem
Wait-ForSyncImportOperationToComplete -PollInterval 1000 -InSqlConnector $NewConnectorItem


Restore-EMIModel
















